package gcode.helloworld.java.socket.linecaller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketException;
import java.util.concurrent.BlockingQueue;
import org.apache.log4j.Logger;

public class Worker extends Thread {
	private Logger log = null;
	private BlockingQueue<Socket> requestQueue	= null;
	private boolean running	= false;
	private Thread workThread	= null;
	private Socket socket = null;
	public Worker(BlockingQueue<Socket> queue) {
		log=Logger.getLogger(getClass());
		requestQueue = queue;
	}

	public void shutdown() throws InterruptedException {
		log.info("shutdown");
		if(this.running){
			this.running=false;
			if(workThread!=null){
				workThread.interrupt();
				if(workThread!=Thread.currentThread()){
					Thread.yield();
					Thread.sleep(500);
				}
			}
		}
	}
	
	public void run(){
		log.info("run");
        running = true;
        workThread=Thread.currentThread();
        try {
	        while(running) {
				socket = this.requestQueue.take();
				try {
					work(socket);
				} catch (SocketException e) {
					log.error("work "+e.getMessage(),e);
				}
	        }
		} catch (InterruptedException e) {
			log.error("Interrupted "+workThread);
		}
	}

	private void work(Socket socket) throws SocketException {
		log.info("work");

    	if(socket==null){
			return ;
		}
		BufferedReader in = null;
		PrintWriter out = null;
		String clientAddress=socket.getInetAddress().toString();
		int clientPort=socket.getPort();
		try {
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			out = new PrintWriter(socket.getOutputStream());//,true);
			String cmd=null;
			while(!socket.isClosed()){
				cmd=readData(in,clientAddress,clientPort);
				if(cmd==null){
					break;
				}
				String rec=handleCommand(cmd,clientAddress,clientPort);
				out.println(rec);
				out.flush();
			}
		} catch (IOException e) {
			log.error("run "+e.getMessage(),e);
		} finally{
			out.close();
			try { in.close(); } catch (IOException e) { log.error("run Exception "+e.getMessage(),e);}
			try { socket.close(); } catch (IOException e) { log.error("run Exception "+e.getMessage(),e);}
		}
	}

	private String readData(BufferedReader in, String clientAddress,
			int clientPort)throws IOException {
		String cmd_CLOSE="<CLOSE "+clientAddress+":"+clientPort+"/>";
		String cmd_DATA_BEGIN="<DATA "+clientAddress+":"+clientPort+">";
		String cmd_DATA_END="</DATA "+clientAddress+":"+clientPort+">";
		if(in==null){
			return null;
		}
		String cmd=in.readLine();
		if(cmd==null||cmd.equals(cmd_CLOSE)){
			return null;
		}
		if(!cmd.equals(cmd_DATA_BEGIN)){
			return cmd;
		}
		String data="";
		while(in!=null){
			cmd=in.readLine();
			if(cmd.equals(cmd_DATA_END)){
				break;
			}
			data+=cmd+"\n";
		}
		return data;
	}

	private String handleCommand(String cmd, String clientAddress, int clientport) {
		log.info("call :["+cmd+"]");
		return clientAddress+":"+clientport;
	}
}
